package com.ang.hutool.thread;

import cn.hutool.core.thread.ThreadUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

/**
 * @author ssang
 * @date 2022-08-02 15:59
 *
 * shutdown 方法将执行平缓的关闭过程：不在接受新的任务，同时等待已经提交的任务执行完成---包括那些还未开始执行的任务
 *
 * shutdownNow 尝试停止所有正在执行的任务; 停止等待任务的处理，并返回等待任务的列表; 该方法返回时，这些等待的任务将从队列中清空
 *
 * isShutdown 判断以前是否调用过shutdown
 *
 * isTerminated 判断全部提交的任务是否完成（保证以前调用过shutdown方法）
 *
 * awaitTermination 调用shutdown方法后，等待全部任务执行完成
 *
 * 注意：awaitTermination 和 shutdown 执行时都会申请锁，awaitTermination 需要在 shutdown 调用后调用，
 *      awaitTermination会在代码中不断检查线程池是否停止（这需要调用 shutdown后等任务全部执行完毕），如果停止，则返回true并释放锁
 */
public class Test01 {
    public static void main(String[] args) {
        Test01 t = new Test01();
        t.test01();
//        t.test02();
    }

    public void test01(){
        ExecutorService executorService = ThreadUtil.newExecutor(5);

        AtomicInteger result = new AtomicInteger(0);
        IntStream.range(0,1000000).forEach(i->{
            CompletableFuture.runAsync(()->{
                int r1 = result.incrementAndGet();
                System.out.println(r1);
                if(r1==1000000){
                    System.out.println("========================"+100000);
                }
            },executorService);
        });

        try {
            //停止接收新的任务并且等待已经提交的任务（包含提交正在执行和提交未执行）执行完成。当所有提交任务执行完毕，线程池即被关闭
            executorService.shutdown();

            if(executorService.awaitTermination(2, TimeUnit.SECONDS)){
                System.out.println("时间超时，强制关闭");
                //他将尝试取消全部运行中的任务，而且再也不启动队列中还没有开始执行的任务
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("======================end");
    }

    /**
     * CountDownLatch
     */
    public void test02(){
        CountDownLatch countDownLatch = new CountDownLatch(100000);

        List<Integer> list = new ArrayList<>();
        CopyOnWriteArrayList<Integer> arrayList = new CopyOnWriteArrayList<>();

        ExecutorService executorService = ThreadUtil.newExecutor(5);
        IntStream.range(0,100000).forEach(i->{
            RunnableTask task = new RunnableTask(arrayList,i,countDownLatch);
            CompletableFuture.runAsync(task,executorService);
        });

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(arrayList.size());
    }

    class RunnableTask implements Runnable {
        CountDownLatch countDownLatch;
        List<Integer> list;
        int i;

        public RunnableTask(List<Integer> list, int i, CountDownLatch countDownLatch){
            this.list = list;
            this.i = i;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            this.list.add(i);
            countDownLatch.countDown();
        }
    }
}
